/*-
 * Copyright (c) 2007 Microsoft
 * All rights reserved.
 */

#pragma once

#include "MPIWaitHandle.h"

namespace Microsoft{
    namespace ComputeCluster{
        namespace MpiNet{
            using namespace System::Threading;
            using namespace System;

            ref class AsyncResult : public System::IAsyncResult
            {
            private:
                bool completed;

                MPI_Request request;
                AsyncCallback^ callback;

            protected:
                bool disposed;

                AsyncResult(AsyncCallback^ callback)
                {
                    if (callback != nullptr)
                        throw gcnew System::NotImplementedException();
                    this->callback = callback;
                }

                virtual void MyDispose(bool)
                {
                    if (!disposed)
                    {
                        disposed = true;
                    }
                }

            public:
                property virtual System::Threading::WaitHandle^ AsyncWaitHandle
                {
                    System::Threading::WaitHandle^ get()
                    {
                        throw gcnew System::NotSupportedException();
                    }
                }

                property virtual bool IsCompleted
                {
                    bool get()
                    {
                        if (!completed) {
                            int flag;
                            int ret;
                            MPI_Request request0 = request;
                            ret = MPI_Test(&request0, &flag, MPI_STATUS_IGNORE);
                            if (ret != MPI_SUCCESS)
                                throw gcnew MPIException(ret);
                            completed = (flag == 1);
                        }

                        return completed;
                    }
                }

                property virtual bool CompletedSynchronously
                {
                    bool get()
                    {
                        return false;
                    }
                }

                property virtual System::Object^ AsyncState
                {
                    System::Object^ get()
                    {
                        throw gcnew System::NotSupportedException();
                    }
                }
 
                virtual bool WaitComplete()
                {
                    if (this->IsCompleted)
                        return false;

                    MPI_Request request0;
                    int ret;

                    request0 = this->request;
                    ret = MPI_Wait(&request0, MPI_STATUS_IGNORE);
                    if (ret != MPI_SUCCESS)
                            throw gcnew MPIException(ret);

                    return true;
                }
 
                !AsyncResult()
                {
                    MyDispose(true);
                    GC::SuppressFinalize(this);
                }

                ~AsyncResult()
                {
                    MyDispose(false);
                }
            };
        }
    }
}